package com.dlc.shop.user.api.manager.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.dlc.shop.bean.app.dto.ShopCartItemDiscountDto;
import com.dlc.shop.bean.app.dto.ShopCartItemDto;
import com.dlc.shop.bean.app.dto.ShopCartOrderDto;
import com.dlc.shop.bean.app.dto.ShopCartOrderMergerDto;
import com.dlc.shop.bean.enums.OrderActivityType;
import com.dlc.shop.bean.enums.OrderType;
import com.dlc.shop.bean.model.ShopCustomer;
import com.dlc.shop.bean.model.UserExtension;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.util.Arith;
import com.dlc.shop.manager.UserLevelOrderManager;
import com.dlc.shop.security.api.util.SecurityUtils;
import com.dlc.shop.service.ShopCustomerService;
import com.dlc.shop.service.UserExtensionService;
import com.dlc.shop.user.common.dao.UserLevelMapper;
import com.dlc.shop.user.common.model.UserLevel;
import com.dlc.shop.user.common.service.UserLevelCategoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @author FrozenWatermelon
 * @date 2021/12/21
 */
@Component
@RequiredArgsConstructor
public class UserLevelOrderManagerImpl implements UserLevelOrderManager {

    private final ShopCustomerService shopCustomerService;
    private final UserLevelMapper userLevelMapper;
    private final UserExtensionService userExtensionService;
    private final UserLevelCategoryService userLevelCategoryService;

    @Override
    public void calculateLevelDiscount(ShopCartOrderMergerDto shopCartOrderMerger) {
        UserExtension extension = userExtensionService.getOne(
                new LambdaQueryWrapper<UserExtension>().eq(UserExtension::getUserId, SecurityUtils.getUser().getUserId()));
        if (Objects.isNull(extension)) {
            return;
        }
        if (extension.getLevel() == null) {
            extension.setLevel(Constant.USER_LEVEL_INIT);
        }
        UserLevel level = userLevelMapper.selectOneAndCategory(extension, Constant.PLATFORM_SHOP_ID);
        if (Objects.isNull(level) || level.getDiscount() > Constant.MAX_LEVEL_DISCOUNT) {
            return;
        }
        List<ShopCartOrderDto> shopCartOrders = shopCartOrderMerger.getShopCartOrders();
        // 获取分类比例
        // 最后计算成长值折扣
        double levelDiscount = 0.0;
        double freeTransFee = 0.0;

        double discount = Arith.sub(10, level.getDiscount());

        List<Long> categoryIds = level.getCategoryIds();
        Set<Long> categorySet = new HashSet<>(categoryIds);

        List<ShopCartItemDto> shopCartItems = new ArrayList<>();
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            // 店铺中的满减项列表
            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrder.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                // 如果是套餐活动跳过循环
                if (Objects.equals(shopCartItemDiscount.getActivityType(), OrderActivityType.COMBO.value())) {
                    continue;
                }
                shopCartItems.addAll(shopCartItemDiscount.getShopCartItems());
            }
        }
        // 折扣金额处理
        handleCartOrder(shopCartItems, level, categorySet, shopCartOrders, levelDiscount, freeTransFee, discount, shopCartOrderMerger);
    }

    private void handleCartOrder(List<ShopCartItemDto> shopCartItems, UserLevel level, Set<Long> categorySet, List<ShopCartOrderDto> shopCartOrders,
                                 double levelDiscount, double freeTransFee, double discount, ShopCartOrderMergerDto shopCartOrderMerger) {
        // 金额最大的一项sku
        Long maxAmountSkuId = 0L;
        // 计算折扣总额
        double totalFee = 0.0;
        double maxAmount = 0.0;
        for (ShopCartItemDto shopCartItem : shopCartItems) {
            // 折扣
            if (level.getDiscountType() == 0 || categorySet.contains(shopCartItem.getCategoryId())) {
                totalFee = Arith.add(totalFee, shopCartItem.getActualTotal());
                maxAmountSkuId = shopCartItem.getActualTotal() > maxAmount ? shopCartItem.getSkuId() : maxAmountSkuId;
                maxAmount = Math.max(shopCartItem.getActualTotal(),maxAmount);
            }
        }
        double maxLevelFeeTotal =  Arith.div(Arith.mul(totalFee, Arith.sub(10, level.getDiscount())), 10, 2);
        // 通过for i找出最后一项，将计算偏差的金额给最后的最大的一项
        for (int shopIndex = 0; shopIndex < shopCartOrders.size(); shopIndex++) {
            ShopCartOrderDto shopCartOrder = shopCartOrders.get(shopIndex);
            // 如果可用范围为自营店不为当前店铺直接下一次循环
            if (level.getDiscountRange() == 1 && !Objects.equals(shopCartOrder.getShopId(), 1L)) {
                continue;
            }
            // 自营店包邮判断
            if (Objects.equals(shopCartOrder.getShopId(), Constant.MAIN_SHOP) && level.getIsFreeFee() == 1) {
                if (shopCartOrder.getTransFee() > 0) {
                    freeTransFee = shopCartOrder.getTransFee();
                    // 平台包邮减免金额
                    shopCartOrder.setPlatformFreeFreightAmount(null == shopCartOrder.getPlatformFreeFreightAmount() ? 0.0 : shopCartOrder.getPlatformFreeFreightAmount());
                    shopCartOrder.setPlatformFreeFreightAmount(Arith.add(shopCartOrder.getPlatformFreeFreightAmount(),freeTransFee));
                }
            }
            // 会员折扣判断（活动订单不计算折扣）
            double reduceSum = 0.0;
            if (!Objects.equals(shopCartOrder.getOrderType(), OrderType.ORDINARY.value())) {
                shopCartOrder.setLevelReduce(reduceSum);
                continue;
            }
            for (int index = 0; index < shopCartItems.size(); index++) {
                ShopCartItemDto shopCartItem = shopCartItems.get(index);
                if (!Objects.equals(shopCartItem.getShopId(), shopCartOrder.getShopId())) {
                    continue;
                }
                double prodDiscount = 0.0;
//                // 判断是否最后一项
                // 如果是金额最大的一项，直接跳过，最后在处理
                if(Objects.equals(shopCartItem.getSkuId(),maxAmountSkuId)){
                    continue;
                }
                // 折扣
                if (level.getDiscountType() == 0 || categorySet.contains(shopCartItem.getCategoryId())) {
                    prodDiscount = Arith.div(Arith.mul(shopCartItem.getActualTotal(), discount), 10, 2);
                    if (Arith.add(Arith.add(levelDiscount, reduceSum), prodDiscount) > maxLevelFeeTotal) {
                        // 总折扣金额减去当前累计的折扣金额，就为最后一件商品分摊的等级优惠金额
                        prodDiscount = Arith.sub(Arith.sub(maxLevelFeeTotal, levelDiscount), reduceSum);
                    }
                }
                // 设置默认值
                shopCartItem.setPlatformShareReduce(null == shopCartItem.getPlatformShareReduce() ? 0.0 : shopCartItem.getPlatformShareReduce());
                // 计算商品分摊的金额
                shopCartItem.setPlatformShareReduce(Arith.add(shopCartItem.getPlatformShareReduce(), prodDiscount));
                shopCartItem.setLevelReduce(prodDiscount);
                reduceSum = Arith.add(reduceSum, Arith.roundByBanker(prodDiscount, 2));
            }
            // 设置店铺的实际总值、积分优惠金额和订单优惠金额
            shopCartOrder.setLevelReduce(reduceSum);
            levelDiscount = Arith.add(levelDiscount, reduceSum);
        }
        // 最后一项处理，将计算偏差的金额给最后的最大的一项
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            // 如果可用范围为自营店不为当前店铺 || 活动订单不计算折扣，直接下一次循环
            boolean unCal = !Objects.equals(shopCartOrder.getOrderType(), OrderType.ORDINARY.value())
                    || (level.getDiscountRange() == 1 && !Objects.equals(shopCartOrder.getShopId(), 1L));
            if (unCal) {
                continue;
            }
            for (ShopCartItemDto shopCartItem : shopCartItems) {
                if (!Objects.equals(shopCartItem.getShopId(), shopCartOrder.getShopId())) {
                    continue;
                }
                // 如果是金额最大的一项，直接跳过，最后在处理
                if (!Objects.equals(shopCartItem.getSkuId(), maxAmountSkuId)) {
                    continue;
                }
                // 总折扣金额减去当前累计的折扣金额，就为最后一件商品分摊的等级优惠金额
                double prodDiscount = Arith.sub(maxLevelFeeTotal, levelDiscount);
                if(prodDiscount == shopCartItem.getActualTotal()){
                    prodDiscount = Arith.sub(shopCartItem.getActualTotal(),0.01);
                }
                // 计算商品分摊的金额
                shopCartItem.setPlatformShareReduce(null == shopCartItem.getPlatformShareReduce() ? 0L : shopCartItem.getPlatformShareReduce());
                shopCartItem.setPlatformShareReduce(Arith.add(shopCartItem.getPlatformShareReduce(), prodDiscount));
                shopCartItem.setLevelReduce(prodDiscount);
                // 设置店铺的实际总值、积分优惠金额和订单优惠金额
                shopCartOrder.setLevelReduce(Arith.add(shopCartOrder.getLevelReduce(), prodDiscount));
                levelDiscount = Arith.add(levelDiscount, prodDiscount);
                break;
            }
        }
        shopCartOrderMerger.setTotalLevelAmount(levelDiscount);
        // 设置运费优惠金额
        shopCartOrderMerger.setFreeTransFee(freeTransFee);
    }

    @Override
    public void calShopLevelDiscount(ShopCartOrderMergerDto shopCartOrderMergerDto) {
        // 基础数据
        String userId = shopCartOrderMergerDto.getUserId();
        // 遍历店铺，查询是否存在会员，存在则计算优惠，不存在则设置品牌会员等级优惠为0
        ShopCustomer shopCustomer;
        UserLevel userLevel;
        List<Long> categoryIds;
        double prodDiscount;
        double orderDiscount;
        double totalDiscount = 0.0;
        double discountRate;
        for (ShopCartOrderDto order : shopCartOrderMergerDto.getShopCartOrders()) {
            // 查找会员等级（不存在，则设置品牌会员优惠金额(shopMemberAmount)==0.0）
            shopCustomer = shopCustomerService.getOne(new LambdaQueryWrapper<ShopCustomer>()
                    .eq(ShopCustomer::getShopId, order.getShopId())
                    .eq(ShopCustomer::getUserId, userId)
                    .ne(ShopCustomer::getLevelType, -1));
            if (shopCustomer == null
                    || shopCustomer.getLevelId() == null) {
                // 不存在会员 or 不存在会员等级
                this.shopMemberZeroAmount(order);
                continue;
            }
            userLevel = userLevelMapper.selectById(shopCustomer.getLevelId());
            if (userLevel == null) {
                // 不存在会员等级
                this.shopMemberZeroAmount(order);
                continue;
            }
            // 查出折扣商品分类
            categoryIds = new ArrayList<>();
            if (userLevel.getDiscountType() == 1) {
                categoryIds = userLevelCategoryService.getCategoryIdByLevelId(userLevel.getId());
            }
            // 计算各店铺订单折扣价格
            discountRate = Arith.sub(10, userLevel.getDiscount());
            // --------------------------
            orderDiscount = 0.0;
            // 邮费计算
            if (userLevel.getIsFreeFee() == 1
                    && order.getTransFee() > 0) {
                order.setFreeTransFee(order.getTransFee());
                order.setTransFee(0.0);
            }
            // 商品价格计算（存在折扣力度，且不是活动订单才进行计算）
            if (userLevel.getDiscount() >= 10.0
                    || !Objects.equals(order.getOrderType(), OrderType.ORDINARY.value())) {
                this.shopMemberZeroAmount(order);
                continue;
            }
            for (ShopCartItemDiscountDto itemCoupon :order.getShopCartItemDiscounts()) {
                for (ShopCartItemDto item : itemCoupon.getShopCartItems()) {
                    // 商品不使用会员价 or 是套餐商品
                    boolean isNotCalMemberAmount = (item.getUseMember() != null && item.getUseMember() == 0)
                            || (Objects.nonNull(item.getComboId()) && item.getComboId() != 0);
                    if (isNotCalMemberAmount) {
                        item.setShopMemberAmount(0.0);
                        continue;
                    }
                    // 指定分类商品 and 商品在指定分类中
                    boolean flag = userLevel.getDiscountType() == 1 && categoryIds.contains(item.getCategoryId());
                    // 全部商品折扣 or (指定分类商品 and 商品在指定分类中) 才计算折扣
                    if (userLevel.getDiscountType() == 0 || flag) {
                        prodDiscount = Arith.div(Arith.mul(item.getActualTotal(), discountRate), 10, 2);
                        item.setShopMemberAmount(prodDiscount);
                        orderDiscount = Arith.add(orderDiscount, prodDiscount);
                    } else {
                        item.setShopMemberAmount(0.0);
                    }
                }
            }
            order.setShopMemberAmount(orderDiscount);
            totalDiscount = Arith.add(totalDiscount, orderDiscount);
        }
        shopCartOrderMergerDto.setShopMemberAmount(totalDiscount);
    }

    private void shopMemberZeroAmount(ShopCartOrderDto shopCartOrderDto) {
        for (ShopCartItemDiscountDto itemCoupon : shopCartOrderDto.getShopCartItemDiscounts()) {
            for (ShopCartItemDto item : itemCoupon.getShopCartItems()) {
                item.setShopMemberAmount(0.0);
            }
        }
        shopCartOrderDto.setShopMemberAmount(0.0);
    }
}
